#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <cerrno>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <functional>
#include <signal.h>
#include <sys/epoll.h>
#include "logMessage.hpp"
#include "Sock.hpp"
#include <fcntl.h>
#define gport 8080
#define default_sort -1
namespace select_ns
{
    using func_t = function<string(const string &)>;
    static const int num = 1024;
    static const int size = 128;
    static const int evnum = 1024;
    class epollServer
    {
    public:
        epollServer(const uint16_t &port = gport) : _port(port), _listensort(-1)
        {
        }
        ~epollServer()
        {
            if (_listensort > 0)
                close(_listensort);
        }
        void Recver(int pos)
        {
            // 接收网络发来的东西,并发回去
            logMessage(NORMAL, "Recver start");
            char buffer[1024];
            // 此时是select发来信号让我们调用recv，所以肯定不会阻塞
            ssize_t n = recv(_ev[pos].data.fd, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                logMessage(NORMAL, "client # %s", buffer);
            }
            else if (n == 0)
            {
                // 表示用户端退出
                epoll_ctl(_epfd, EPOLL_CTL_DEL, _ev[pos].data.fd, _ev);
                close(_ev[pos].data.fd);
                logMessage(NORMAL, "client quit");
                return;
            }
            else
            {
                logMessage(FATAL, "recv err :%s", strerror(errno));
                epoll_ctl(_epfd, EPOLL_CTL_DEL, _ev[pos].data.fd, _ev);
                close(_ev[pos].data.fd);
                return;
            }
        }
        void Accepter()
        {
            string client_ip;
            uint16_t client_port;
            // accept得到的sock就是后续文件操作的“文件指针”
            int sock = Sock::Accept(_listensort, &client_ip, &client_port);
            logMessage(NORMAL, "accept sucess [%s][%d]", client_ip.c_str(), client_port);
            // 把新得到的sock加入epoll让他帮我管理
            struct epoll_event rev;
            rev.data.fd = sock;
            rev.events = EPOLLIN;
            epoll_ctl(_epfd, EPOLL_CTL_ADD, sock, &rev);
        }
        void HanderEvent(int readyNum)
        {
            logMessage(NORMAL, "Hander in");
            for (int i = 0; i < readyNum; i++)
            {
                __uint32_t event = _ev[i].events;
                int sock = _ev[i].data.fd;
                if (sock == _listensort && (event & EPOLLIN))
                    Accepter();
                else if (event & EPOLLIN)
                    Recver(i);
            }
            logMessage(NORMAL, "Hander out");
        }
        void Init()
        {
            _listensort = Sock::Socket();
            Sock::Bind(_listensort, _port);
            Sock::Listen(_listensort);
            // 1.创建epoll模型
            _epfd = epoll_create(size);
            _ev = new struct epoll_event[evnum];
            // 2.添加listen到epoll中
            _ev[0].events = EPOLLIN;
            _ev[0].data.fd = _listensort;
            epoll_ctl(_epfd, EPOLL_CTL_ADD, _listensort, _ev);
        }
        void start()
        {
            while (1)
            {
                int timeout = 1000;
                int n = epoll_wait(_epfd, _ev, evnum, timeout);
                switch (n)
                {
                case 0:
                    logMessage(NORMAL, "timeout...");
                    break;
                case -1:
                    logMessage(ERROR, "epoll_wait error :%s", strerror(errno));
                    return;
                    break;
                default:
                    logMessage(NORMAL, "wait success");
                    HanderEvent(n);
                    break;
                }
            }
        }

    private:
        int _port;
        int _listensort;
        int _epfd;
        struct epoll_event *_ev;
    };
}